#include "Listener.h"
#include "App.h"
#include "BMFont.h"

#include "BMFontMessages.h"

TextureID	scratchSprites;

void	fontRenderString(const char*	str,vec3&	o,vec3&	u,vec3&	v){
	float	cursorPos=0.0f;
	float	scale=100.0f;
	float*	quad=&Text_uvs[0][0];
	float	defTxtHeight=(quad[1]+quad[3]+quad[5]+quad[7])*0.5f;
	vec3	tbnds(0,0,0);
	vec3	lnbnds(0,defTxtHeight,0);
	float	baseline=0.0f;
	float	lnwidth=0.0f;
	
	for(int ci=0;str[ci];ci++){
		unsigned char c=str[ci];
		if(c=='\n'){
			baseline+=lnbnds.y;
			lnbnds=vec3(0,defTxtHeight,0);
			continue;
		}
		int qid=Text_lut[c];
		quad=&Text_uvs[qid][0];
		vec2 dim(quad[0]+quad[2]+quad[4]+quad[6],quad[1]+quad[3]+quad[5]+quad[7]);
		dim*=0.25f;
		dim-=vec2(quad[0],quad[1]);
		dim=vec2(abs(dim.x),abs(dim.y))*2.0f;
		if(lnbnds.y<dim.y)lnbnds.y=dim.y;
		if(tbnds.y<lnbnds.y+baseline)tbnds.y=lnbnds.y+baseline;
		lnbnds.x+=dim.x;
		if(tbnds.x<lnbnds.x)tbnds.x=lnbnds.x;
	}
	int just=-1;
	vec3 org;
	if(just==-1){
		org=vec3(0,tbnds.y*-0.5f,0);
		org.y*=-3.0f;
		org=((org.x*u)+(org.y*v))*scale;
		org+=o;
	}else if(just==0){
		vec3	org=tbnds*-0.5f;
		org.y*=-3.0f;
		org=((org.x*u)+(org.y*v))*scale;
		org+=o;
	}else{
		org=vec3(lnbnds.x*-1.0f,tbnds.y*-0.5f,0);
		org.y*=-3.0f;
		org=((org.x*u)+(org.y*v))*scale;
		org+=o;
	}
	tbnds=vec3(0,0,0);
	lnbnds=vec3(0,defTxtHeight,0);
	baseline=0.0f;
	lnwidth=0.0f;
	for(int ci=0;str[ci];ci++){
		unsigned char c=str[ci];
		if(c=='\n'){
			baseline-=lnbnds.y;
			lnbnds=vec3(0,defTxtHeight,0);
			cursorPos=0.0f;
			continue;
		}
		int qid=Text_lut[c];
		quad=&Text_uvs[qid][0];
		vec2 dim(quad[0]+quad[2]+quad[4]+quad[6],quad[1]+quad[3]+quad[5]+quad[7]);
		dim*=0.25f;
		dim-=vec2(quad[0],quad[1]);
		dim=vec2(abs(dim.x),abs(dim.y))*2.0f;
		if(lnbnds.y<dim.y)lnbnds.y=dim.y;
		if(tbnds.y<lnbnds.y+baseline)tbnds.y=lnbnds.y+baseline;
		lnbnds.x+=dim.x;
		if(tbnds.x<lnbnds.x)tbnds.x=lnbnds.x;

		vec3	cp=((((cursorPos+(dim.x*0.5f))*u)+(baseline*v))*scale)+org;

		vec3	du=(dim.x*u)*scale*0.5f;
		vec3	dv=(dim.y*v)*scale*0.5f;
		vec3	lq[4]={cp+du+dv,cp-du+dv,cp-du-dv,cp+du-dv};
		for(int t=0;t<4;t++){
			glTexCoord2fv(&quad[t*2]);
			glVertex3fv(lq[t]);
		}
		cursorPos+=dim.x;
	}
	/*
	for(int ci=0;str[ci];ci++){
		unsigned char c=str[ci];
		int qid=Text_lut[c];
		float*	quad=&Text_uvs[qid][0];
		vec2 dim(quad[0]+quad[2]+quad[4]+quad[6],quad[1]+quad[3]+quad[5]+quad[7]);
		dim*=0.25f;
		dim-=vec2(quad[0],quad[1]);
		dim=vec2(abs(dim.x),abs(dim.y));
		vec3	cp=((cursorPos*u)*scale)+org;
		vec3	du=(dim.x*u)*scale;
		vec3	dv=(dim.y*v)*scale;
		vec3	lq[4]={cp+du+dv,cp-du+dv,cp-du-dv,cp+du-dv};
		for(int t=0;t<4;t++){
			glTexCoord2fv(&quad[t*2]);
			glVertex3fv(lq[t]);
		}
		cursorPos+=dim.x*2;
	}*/
}



TextureID getTextureByName(char*	name,TextureFilter	filter,uint flags=0);


class BMFontListener	: public Listener
{
public:
	virtual bool	message(const char *msg=null,void*	params=null){
		if(msg=="fontRenderString"){
			renderStringParams*	p=(renderStringParams*)params;
			fontRenderString(p->str,p->vo[0],p->vu[0],p->vv[0]);
		}else if(msg=="fontStartRendering"){
			static	ShaderID	txonlyShader=-1;
			static	TextureID	scratchSprites=-1;
			Renderer*	renderer=gApp->getRenderer();
			if(txonlyShader==-1)
				txonlyShader=getShader("unlit.shd","");
			renderer->setShader(txonlyShader);
			if(scratchSprites==-1)
				if ((scratchSprites = getTextureByName(TEX_PATH "scratchSprites0001.bmp", FILTER_BILINEAR)) == TEXTURE_NONE) return false;
			renderer->setTexture(TMU0, scratchSprites);
			renderer->setBlending(GL_ONE_MINUS_DST_COLOR,GL_SRC_ALPHA);//GL_ONE_MINUS_SRC_ALPHA);
			renderer->setMask(COLOR);
			renderer->apply();
		}
		return true;
	}
	BMFontListener(){
		Listener::listen(this,"fontRenderString");
		Listener::listen(this,"fontStartRendering");
	}
};

BMFontListener	gBMFontListener;
